///////////////////////////////////////////////////////////////////////////////////////////////////
//
// PROJECT : Arirang family
//
// DATE    : 2008.10.23
//
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// FILE  : Arirang_OP32.h
//
// NOTES : Optimized code of Arirang family
//
//         Based on 32-bit platform (with four 32-bit S-box and sixteen 32-bit S-box version)

///////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef _ARIRANG_OP32_H__
#define _ARIRANG_OP32_H__ 100
#include <stdlib.h>
#include "SHA3api_OP32.h"


///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Macro

// Define the Endianness
#undef BIG_ENDIAN
#undef LITTLE_ENDIAN

#if defined(USER_BIG_ENDIAN)
	#define BIG_ENDIAN
#elif defined(USER_LITTLE_ENDIAN)
	#define LITTLE_ENDIAN
#else
//	#if 0
//		#define BIG_ENDIAN
//	#elif defined(_MSC_VER)
		#define LITTLE_ENDIAN
//	#else
//		#error
//	#endif
#endif

// Left and rigth rotation
#if defined(_MSC_VER)
	#define ROTL_DWORD(x, n) _lrotl((x), (n))
	#define ROTR_DWORD(x, n) _lrotr((x), (n))
#else
	#define ROTL_DWORD(x, n) ( (DWORD)((x) << (n)) | (DWORD)((x) >> (32-(n))) )
	#define ROTR_DWORD(x, n) ( (DWORD)((x) >> (n)) | (DWORD)((x) << (32-(n))) )
#endif

#define ROTL_DWORD1(x1, x2, n) ( (DWORD)((x1) << (n)) | (DWORD)((x2) >> (32-(n))) )
#define ROTL_DWORD2(x1, x2, n) ( (DWORD)((x2) << (n)) | (DWORD)((x1) >> (32-(n))) )

#define ROTR_DWORD1(x1, x2, n) ( (DWORD)((x1) >> (n)) | (DWORD)((x2) << (32-(n))) )
#define ROTR_DWORD2(x1, x2, n) ( (DWORD)((x2) >> (n)) | (DWORD)((x1) << (32-(n))) );

// Reverse the byte order of DWORD and WORD.
#define ENDIAN_REVERSE_DWORD(dwS)	( (ROTL_DWORD((dwS),  8) & 0x00ff00ff) | (ROTL_DWORD((dwS), 24) & 0xff00ff00) )

// Move DWORD type to BYTE type and BYTE type to DWORD type
#if defined(BIG_ENDIAN)
	#define BIG_B2D(B, D)		D = *(DWORD *)(B)
	#define BIG_D2B(D, B)		*(DWORD *)(B) = (DWORD)(D)
	#define LITTLE_B2D(B, D)	D = ENDIAN_REVERSE_DWORD(*(DWORD *)(B))
	#define LITTLE_D2B(D, B)	*(DWORD *)(B) = ENDIAN_REVERSE_DWORD(D)
#elif defined(LITTLE_ENDIAN)
	#define BIG_B2D(B, D)		D = ENDIAN_REVERSE_DWORD(*(DWORD *)(B))
	#define BIG_D2B(D, B)		*(DWORD *)(B) = ENDIAN_REVERSE_DWORD(D)
	#define LITTLE_B2D(B, D)	D = *(DWORD *)(B)
	#define LITTLE_D2B(D, B)	*(DWORD *)(B) = (DWORD)(D)
#endif


///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Function

void gen_tabs(void);
void Arirang_Compression256(hashState *state);
void Arirang_Compression512(hashState *state);


#endif
